package com.zjhome.cloudnote.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import com.zjhome.cloudnote.constant.ConstantKey;
import com.zjhome.cloudnote.exception.TokenException;
import com.zjhome.cloudnote.service.impl.GrantedAuthorityImpl;
import com.zjhome.cloudnote.util.SerializeUtil;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;

/**
 * 自定义JWT认证过滤器
 * >> 该类继承自BasicAuthenticationFilter,早doFilterInternal方法中，
 * >> 从http头的Authorization项读取token数据，然后用Jwts包提供的方法校验token的合法性。
 * >> 如果校验通过，就认为这是一个取得授权的合法请求
 * 
 * @author 0283000121
 *
 */
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
	private static final Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
			
	public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
		super(authenticationManager);
	}
	
	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 
		String header = request.getHeader("Authorization");
//		if (header == null || !header.startsWith("Bearer ")) {
		if (header == null) {
			chain.doFilter(request, response);
			return;
		}
		
		// 用户验证
		UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
		SecurityContextHolder.getContext().setAuthentication(authentication);
		chain.doFilter(request, response);
	}
	
	private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
		long start = System.currentTimeMillis();
		String token = request.getHeader("Authorization");
		if (token == null || token.isEmpty()) {
			throw new TokenException("Token为空");
		}
		
		// parse the token.		
		try {
//			String subject = Jwts.parser()
//				.setSigningKey(ConstantKey.SIGNING_KEY)
//				.parseClaimsJws(token.replace("Bearer ", ""))
//				.getBody()
//				.getSubject();
			
			Claims claims = Jwts.parser()
					.setSigningKey(ConstantKey.SIGNING_KEY)
//					.parseClaimsJws(token.replace("Bearer ", ""))
					.parseClaimsJws(token)
					.getBody();
			
			long end = System.currentTimeMillis();
			logger.info("执行时间：{}", (end - start) + " 毫秒");
//			if (subject != null) {
//				String[] split = subject.split("-")[1].split(",");
//				ArrayList<GrantedAuthority> authorities = new ArrayList<>();
//				for(int i=0; i<split.length; i++) {
//					authorities.add(new GrantedAuthorityImpl(split[i]));
//				}
//				return new UsernamePasswordAuthenticationToken(subject, null, authorities);
//			}
			
			if (claims != null) {				
				Object userid = claims.get("userid");
				ArrayList roles = (ArrayList)claims.get("roles");
				
				ArrayList<GrantedAuthority> authorities = new ArrayList<>();
				for(int i=0; i<roles.size(); i++) {
					Object item = roles.get(i);
					authorities.add(new GrantedAuthorityImpl((String)item));
				}
				
				return new UsernamePasswordAuthenticationToken(claims.get("userid"), null, authorities);
			}
			
		} catch (ExpiredJwtException e) {
			logger.error("Token已过期：{} " + e);
			throw new TokenException("Token已过期");
		} catch (UnsupportedJwtException e) {
			logger.error("Token格式错误: {} " + e);
			throw new TokenException("Token格式错误");
		} catch (MalformedJwtException e) {
			logger.error("Token没有被正确构造: {} " + e);
			throw new TokenException("Token没有被正确构造");
		} catch (SignatureException e) {
			logger.error("签名失败: {} " + e);
			throw new TokenException("签名失败");
		} catch (IllegalArgumentException e) {
			logger.error("非法参数异常: {} " + e);
			throw new TokenException("非法参数异常");
		} 
//		catch (ClassNotFoundException e) {
//			logger.error("序列化失败： {} " + e);
//			throw new TokenException("序列化失败");
//		} 
//		catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
		return null;
	}
}
